package vn.vfriends.id.bean;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;
import javax.inject.Named;
import org.primefaces.context.RequestContext;
import org.primefaces.model.DualListModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vn.vfriends.id.jpa.entity.Group;
import vn.vfriends.id.jpa.entity.Role;
import vn.vfriends.id.jpa.entity.User;
import vn.vfriends.id.service.GroupService;
import vn.vfriends.id.service.RoleService;
import vn.vfriends.id.service.UserService;

/**
 *
 * @author tuan@vfriends.vn
 */
@Named
@ConversationScoped
public class GroupBean implements Serializable {
    
    private final Logger logger = LoggerFactory.getLogger(GroupBean.class);
    
    @Inject private GroupService groupService;
    
    @Inject private UserService userService;
    
    @Inject private RoleService roleService;
    
    @Inject private Conversation conversation;
    
    private Group[] selectedGroups;
    private Group group;
    private List<Group> groupList;
    private List<User> userList;
    private User[] selectedUsers;
    private User[] selectedAddUsers;
    private DualListModel<Role> roleModels;

    @PostConstruct
    public void init() {
        groupList = groupService.find();
        userList = userService.find();
        List<Role> source = roleService.find();
        roleModels = new DualListModel<Role>(source, new ArrayList<Role>());
    }
    
    public Conversation getConversation() {
        return conversation;
    }
    
    public Group getGroup() {
        return group;
    }

    public void setGroup(Group group) {
        this.group = group;
    }

    public Group[] getSelectedGroups() {
        return selectedGroups;
    }

    public void setSelectedGroups(Group[] selectedGroups) {
        this.selectedGroups = selectedGroups;
    }

    public DualListModel<Role> getRoleModels() {
        return roleModels;
    }

    public void setRoleModels(DualListModel<Role> roleModels) {
        this.roleModels = roleModels;
    }
    
    public List<Group> getGroupList() {
        return this.groupList;
    }
    
    public List<User> getUserList() {
        return this.userList;
    }
    
    public Group.GroupCode[] getGroupCodes() {
        return Group.GroupCode.values();
    }
    
    public Group getGroup(String name){
        return this.groupService.findByName(name);
    }

    public User[] getSelectedUsers() {
        return selectedUsers;
    }

    public void setSelectedUsers(User[] selectedUsers) {
        this.selectedUsers = selectedUsers;
    }

    public User[] getSelectedAddUsers() {
        return selectedAddUsers;
    }

    public void setSelectedAddUsers(User[] selectedAddUsers) {
        this.selectedAddUsers = selectedAddUsers;
    }

    private void initRoleModels() {
        List<Role> roleList = this.roleService.find();
        for (Role role : this.group.getRoles()) {
            roleList.remove(role);
        }
        this.roleModels.setSource(roleList);
        this.roleModels.setTarget(this.group.getRoles());
    }
    
    public void preNewAction() {
        group = new Group();
        
        if (conversation.isTransient()) {
            conversation.begin();
        }
    }
    
    public String preViewAction() {
        String outcome = "";
        FacesContext context = FacesContext.getCurrentInstance();
        
        try {
            if (conversation.isTransient()) {
                conversation.begin();
            }
            
            if(this.group != null) {
                this.initRoleModels();
                outcome = "view?faces-redirect=true";
            } else if (this.selectedGroups == null || this.selectedGroups.length == 0) {
                if (RequestContext.getCurrentInstance() != null) {
                    RequestContext.getCurrentInstance().addCallbackParam("invalid", true);
                }
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Hãy chọn một nhóm người dùng", ""));
            } else if (this.selectedGroups.length > 1) {
                if (RequestContext.getCurrentInstance() != null) {
                    RequestContext.getCurrentInstance().addCallbackParam("invalid", true);
                }
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Hãy chọn chỉ một nhóm người dùng", ""));
            } else {
                this.group = this.selectedGroups[0];
                this.initRoleModels();
                outcome = "view?faces-redirect=true";
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),""));
        }
        return outcome;
    }
    
    public String preEditAction() {
        String outcome = null;
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            if (conversation.isTransient()) {
                conversation.begin();
            }
            
            if(this.group != null){
                List<Role> roleList = this.roleService.find();
                for(Role role : this.group.getRoles()){
                    roleList.remove(role);
                }
                this.roleModels.setSource(roleList);
                this.roleModels.setTarget(this.group.getRoles());
                outcome = "edit?faces-redirect=true";
            } else if (this.selectedGroups == null || this.selectedGroups.length == 0) {
                if (RequestContext.getCurrentInstance() != null) {
                    RequestContext.getCurrentInstance().addCallbackParam("invalid", true);
                }
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Hãy chọn một nhóm người dùng", ""));
            } else if (this.selectedGroups.length > 1) {
                if (RequestContext.getCurrentInstance() != null) {
                    RequestContext.getCurrentInstance().addCallbackParam("invalid", true);
                }
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Hãy chọn chỉ một nhóm người dùng", ""));
            } else {
                this.group = this.selectedGroups[0];
                List<Role> roleList = this.roleService.find();
                for(Role role : this.group.getRoles()){
                    roleList.remove(role);
                }
                this.roleModels.setSource(roleList);
                this.roleModels.setTarget(this.group.getRoles());
                outcome = "edit?faces-redirect=true";
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),""));

        }
        return outcome;
    }
    
    public void preDeleteAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            if (conversation.isTransient()) {
                conversation.begin();
            }
            if ((this.group == null) && (this.selectedGroups == null || this.selectedGroups.length == 0)) {
                if (RequestContext.getCurrentInstance() != null) {
                    RequestContext.getCurrentInstance().addCallbackParam("invalid", true);
                }
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Hãy chọn nhóm người dùng", ""));
            }
        } catch (Exception e) {
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),""));
        }
    }
    
    public void preRemoveAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        try {
            if (this.selectedUsers == null || this.selectedUsers.length == 0) {
                if (RequestContext.getCurrentInstance() != null) {
                    RequestContext.getCurrentInstance().addCallbackParam("invalid", true);
                }
                context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Hãy chọn người dùng", ""));
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), ""));
        }
    }
    
//    public void preAddAction() {
//        this.selectedUsers = null;
//    }
    
    public String updateAction() {
        try {
            group.setRoles(new ArrayList<Role>());
            for(Role role : this.roleModels.getTarget()){
                group.getRoles().add(role);
            }
            this.groupService.edit(group);
            return "view?faces-redirect=true";
        } catch (Exception ex) {
            this.logger.error(ex.getMessage(), ex);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(),""));
            return null;
        }
    }
    
    public String cancelAction() {
        conversation.end();
        return "list?faces-redirect=true";
    }
    
    public String saveAction() {
        try {
            group.setRoles(this.roleModels.getTarget());
            this.groupService.create(group);
            return "view?faces-redirect=true";
        } catch (Exception ex) {
            this.logger.error(ex.getMessage(), ex);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, ex.getMessage(),""));
            return null;
        }
    }
    
    public void deleteAction() {
        try {
            if(this.group != null)
                this.groupService.destroy(this.group.getId());
            else
                for(Group selectedGroup : selectedGroups)                
                    this.groupService.destroy(selectedGroup.getId());
            if(!conversation.isTransient())
                conversation.end();
            FacesContext.getCurrentInstance().getExternalContext().redirect("list.jsf");
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),""));
        }
    }
    
    public void removeUserAction() {
        try {
            for (User selectedUser : selectedUsers) {
                group.getUsers().remove(selectedUser);
            }
            this.groupService.edit(group);
            this.selectedUsers = null;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),""));
        }
    }
    
    public void addUserAction() {
        try {
            if (this.selectedAddUsers == null || this.selectedAddUsers.length == 0) {
                return;
            }
            
            List<User> userList = this.group.getUsers();
            for (User selectedUser : selectedAddUsers) {
                if(userList.contains(selectedUser))
                    continue;
                else
                    userList.add(selectedUser);
            }
            this.groupService.edit(group);
            //this.selectedUsers = null;
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),""));
        }
    }
}
